<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>Assimp: Data Structures</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td style="padding-left: 0.5em;">
   <div id="projectname">Assimp
   &#160;<span id="projectnumber">v3.0 (July 2012)</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.1.1 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="namespaces.html"><span>Namespaces</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
    </ul>
  </div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Data Structures </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The assimp library returns the imported data in a collection of structures.</p>
<p><a class="el" href="structai_scene.html" title="The root structure of the imported data.">aiScene</a> forms the root of the data, from here you gain access to all the nodes, meshes, materials, animations or textures that were read from the imported file. The <a class="el" href="structai_scene.html" title="The root structure of the imported data.">aiScene</a> is returned from a successful call to <a class="el" href="class_assimp_1_1_importer.html#a174418ab41d5b8bc51a044895cb991e5" title="Reads the given file and returns its contents if successful.">Assimp::Importer::ReadFile()</a>, <a class="el" href="cimport_8h.html#a09fe8ba0c8e91bf04b4c29556be53b6d" title="Reads the given file and returns its content.">aiImportFile()</a> or <a class="el" href="cimport_8h.html#ae2b9815cac53dfcb2bf09aa9d8649894" title="Reads the given file using user-defined I/O functions and returns its content.">aiImportFileEx()</a> - see the <a class="el" href="usage.html">Usage page </a> for further information on how to use the library.</p>
<p>By default, all 3D data is provided in a right-handed coordinate system such as OpenGL uses. In this coordinate system, +X points to the right, -Z points away from the viewer into the screen and +Y points upwards. Several modeling packages such as 3D Studio Max use this coordinate system as well (or a rotated variant of it). By contrast, some other environments use left-handed coordinate systems, a prominent example being DirectX. If you need the imported data to be in a left-handed coordinate system, supply the <a class="el" href="postprocess_8h.html#a64795260b95f5a4b3f3dc1be4f52e410a133fd1162674e68bf8cd17070898a936">aiProcess_MakeLeftHanded</a> flag to the ReadFile() function call.</p>
<p>The output face winding is counter clockwise. Use <a class="el" href="postprocess_8h.html#a64795260b95f5a4b3f3dc1be4f52e410a429a11bf7ace46f039f55de895505d4a">aiProcess_FlipWindingOrder</a> to get CW data. </p>
<div class="fragment"><div class="line">x2</div>
<div class="line">  </div>
<div class="line">            x1</div>
<div class="line">        x0</div>
</div><!-- fragment --><p>Outputted polygons can be literally everything: they're probably concave, self-intersecting or non-planar, although our built-in triangulation (<a class="el" href="postprocess_8h.html#a64795260b95f5a4b3f3dc1be4f52e410a9c3de834f0307f31fa2b1b6d05dd592b">aiProcess_Triangulate</a> postprocessing step) doesn't handle the two latter.</p>
<p>The output UV coordinate system has its origin in the lower-left corner: </p>
<div class="fragment"><div class="line">0y|1y ---------- 1x|1y </div>
<div class="line"> |                |</div>
<div class="line"> |                |</div>
<div class="line"> |                |</div>
<div class="line">0x|0y ---------- 1x|0y</div>
</div><!-- fragment --><p> Use the <a class="el" href="postprocess_8h.html#a64795260b95f5a4b3f3dc1be4f52e410a06922b6a1f1cd8186f9fdafb471c813e">aiProcess_FlipUVs</a> flag to get UV coordinates with the upper-left corner als origin.</p>
<p>All matrices in the library are row-major. That means that the matrices are stored row by row in memory, which is similar to the OpenGL matrix layout. A typical 4x4 matrix including a translational part looks like this: </p>
<div class="fragment"><div class="line">X1  Y1  Z1  T1</div>
<div class="line">X2  Y2  Z2  T2</div>
<div class="line">X3  Y3  Z3  T3</div>
<div class="line">0   0   0   1</div>
</div><!-- fragment --><p>... with (X1, X2, X3) being the X base vector, (Y1, Y2, Y3) being the Y base vector, (Z1, Z2, Z3) being the Z base vector and (T1, T2, T3) being the translation part. If you want to use these matrices in DirectX functions, you have to transpose them.</p>
<hr/>
<p><b>11.24.09:</b> We changed the orientation of our quaternions to the most common convention to avoid confusion. However, if you're a previous user of <a class="el" href="namespace_assimp.html" title="Assimp&#39;s CPP-API and all internal APIs.">Assimp</a> and you update the library to revisions beyond SVNREV 502, you have to adapt your animation loading code to match the new quaternion orientation.</p>
<hr/>
<h1><a class="anchor" id="hierarchy"></a>
The Node Hierarchy</h1>
<p>Nodes are little named entities in the scene that have a place and orientation relative to their parents. Starting from the scene's root node all nodes can have 0 to x child nodes, thus forming a hierarchy. They form the base on which the scene is built on: a node can refer to 0..x meshes, can be referred to by a bone of a mesh or can be animated by a key sequence of an animation. DirectX calls them "frames", others call them "objects", we call them <a class="el" href="structai_node.html" title="A node in the imported hierarchy.">aiNode</a>.</p>
<p>A node can potentially refer to single or multiple meshes. The meshes are not stored inside the node, but instead in an array of <a class="el" href="structai_mesh.html" title="A mesh represents a geometry or model with a single material.">aiMesh</a> inside the <a class="el" href="structai_scene.html" title="The root structure of the imported data.">aiScene</a>. A node only refers to them by their array index. This also means that multiple nodes can refer to the same mesh, which provides a simple form of instancing. A mesh referred to by this way lives in the node's local coordinate system. If you want the mesh's orientation in global space, you'd have to concatenate the transformations from the referring node and all of its parents.</p>
<p>Most of the file formats don't really support complex scenes, though, but a single model only. But there are more complex formats such as .3ds, .x or .collada scenes which may contain an arbitrary complex hierarchy of nodes and meshes. I for myself would suggest a recursive filter function such as the following pseudocode:</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> CopyNodesWithMeshes( <a class="code" href="structai_node.html" title="A node in the imported hierarchy.">aiNode</a> node, SceneObject targetParent, Matrix4x4 accTransform)</div>
<div class="line">{</div>
<div class="line">  SceneObject parent;</div>
<div class="line">  Matrix4x4 transform;</div>
<div class="line"></div>
<div class="line">  <span class="comment">// if node has meshes, create a new scene object for it</span></div>
<div class="line">  <span class="keywordflow">if</span>( node.<a class="code" href="structai_node.html#a7a411079096f86d1e96b6368d237d897" title="The number of meshes of this node.">mNumMeshes</a> &gt; 0)</div>
<div class="line">  {</div>
<div class="line">    SceneObjekt newObject = <span class="keyword">new</span> SceneObject;</div>
<div class="line">    targetParent.addChild( newObject);</div>
<div class="line">    <span class="comment">// copy the meshes</span></div>
<div class="line">    CopyMeshes( node, newObject);</div>
<div class="line"></div>
<div class="line">    <span class="comment">// the new object is the parent for all child nodes</span></div>
<div class="line">    parent = newObject;</div>
<div class="line">    transform.SetUnity();</div>
<div class="line">  } <span class="keywordflow">else</span></div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// if no meshes, skip the node, but keep its transformation</span></div>
<div class="line">    parent = targetParent;</div>
<div class="line">    transform = node.<a class="code" href="structai_node.html#afa2a7210e5ba675d239f3050b03c6455" title="The transformation relative to the node&#39;s parent.">mTransformation</a> * accTransform;</div>
<div class="line">  }</div>
<div class="line"></div>
<div class="line">  <span class="comment">// continue for all child nodes</span></div>
<div class="line">  <span class="keywordflow">for</span>( all node.<a class="code" href="structai_node.html#a8424402c9124516e98e6ddff064693e9" title="The child nodes of this node.">mChildren</a>)</div>
<div class="line">    CopyNodesWithMeshes( node.<a class="code" href="structai_node.html#a8424402c9124516e98e6ddff064693e9" title="The child nodes of this node.">mChildren</a>[a], parent, transform);</div>
<div class="line">}</div>
</div><!-- fragment --><p>This function copies a node into the scene graph if it has children. If yes, a new scene object is created for the import node and the node's meshes are copied over. If not, no object is created. Potential child objects will be added to the old targetParent, but there transformation will be correct in respect to the global space. This function also works great in filtering the bone nodes - nodes that form the bone hierarchy for another mesh/node, but don't have any mesh themselves.</p>
<h1><a class="anchor" id="meshes"></a>
Meshes</h1>
<p>All meshes of an imported scene are stored in an array of aiMesh* inside the <a class="el" href="structai_scene.html" title="The root structure of the imported data.">aiScene</a>. Nodes refer to them by their index in the array and providing the coordinate system for them, too. One mesh uses only a single material everywhere - if parts of the model use a different material, this part is moved to a separate mesh at the same node. The mesh refers to its material in the same way as the node refers to its meshes: materials are stored in an array inside <a class="el" href="structai_scene.html" title="The root structure of the imported data.">aiScene</a>, the mesh stores only an index into this array.</p>
<p>An <a class="el" href="structai_mesh.html" title="A mesh represents a geometry or model with a single material.">aiMesh</a> is defined by a series of data channels. The presence of these data channels is defined by the contents of the imported file: by default there are only those data channels present in the mesh that were also found in the file. The only channels guarenteed to be always present are <a class="el" href="structai_mesh.html#a65441c89080d9343de64515f74a64415" title="Vertex positions.">aiMesh::mVertices</a> and <a class="el" href="structai_mesh.html#a6593ae5a5861f69e2576447054d01053" title="The faces the mesh is constructed from.">aiMesh::mFaces</a>. You can test for the presence of other data by testing the pointers against NULL or use the helper functions provided by <a class="el" href="structai_mesh.html" title="A mesh represents a geometry or model with a single material.">aiMesh</a>. You may also specify several post processing flags at Importer::ReadFile() to let assimp calculate or recalculate additional data channels for you.</p>
<p>At the moment, a single <a class="el" href="structai_mesh.html" title="A mesh represents a geometry or model with a single material.">aiMesh</a> may contain a set of triangles and polygons. A single vertex does always have a position. In addition it may have one normal, one tangent and bitangent, zero to AI_MAX_NUMBER_OF_TEXTURECOORDS (4 at the moment) texture coords and zero to AI_MAX_NUMBER_OF_COLOR_SETS (4) vertex colors. In addition a mesh may or may not have a set of bones described by an array of <a class="el" href="structai_bone.html" title="A single bone of a mesh.">aiBone</a> structures. How to interpret the bone information is described later on.</p>
<h1><a class="anchor" id="material"></a>
Materials</h1>
<p>See the <a class="el" href="materials.html">Material System Page. </a></p>
<h1><a class="anchor" id="bones"></a>
Bones</h1>
<p>A mesh may have a set of bones in the form of <a class="el" href="structai_bone.html" title="A single bone of a mesh.">aiBone</a> structures.. Bones are a means to deform a mesh according to the movement of a skeleton. Each bone has a name and a set of vertices on which it has influence. Its offset matrix declares the transformation needed to transform from mesh space to the local space of this bone.</p>
<p>Using the bones name you can find the corresponding node in the node hierarchy. This node in relation to the other bones' nodes defines the skeleton of the mesh. Unfortunately there might also be nodes which are not used by a bone in the mesh, but still affect the pose of the skeleton because they have child nodes which are bones. So when creating the skeleton hierarchy for a mesh I suggest the following method:</p>
<p>a) Create a map or a similar container to store which nodes are necessary for the skeleton. Pre-initialise it for all nodes with a "no". <br/>
 b) For each bone in the mesh: <br/>
 b1) Find the corresponding node in the scene's hierarchy by comparing their names. <br/>
 b2) Mark this node as "yes" in the necessityMap. <br/>
 b3) Mark all of its parents the same way until you 1) find the mesh's node or 2) the parent of the mesh's node. <br/>
 c) Recursively iterate over the node hierarchy <br/>
 c1) If the node is marked as necessary, copy it into the skeleton and check its children <br/>
 c2) If the node is marked as not necessary, skip it and do not iterate over its children. <br/>
</p>
<p>Reasons: you need all the parent nodes to keep the transformation chain intact. For most file formats and modelling packages the node hierarchy of the skeleton is either a child of the mesh node or a sibling of the mesh node but this is by no means a requirement so you shouldn't rely on it. The node closest to the root node is your skeleton root, from there you start copying the hierarchy. You can skip every branch without a node being a bone in the mesh - that's why the algorithm skips the whole branch if the node is marked as "not necessary".</p>
<p>You should now have a mesh in your engine with a skeleton that is a subset of the imported hierarchy.</p>
<h1><a class="anchor" id="anims"></a>
Animations</h1>
<p>An imported scene may contain zero to x <a class="el" href="structai_animation.html" title="An animation consists of keyframe data for a number of nodes.">aiAnimation</a> entries. An animation in this context is a set of keyframe sequences where each sequence describes the orientation of a single node in the hierarchy over a limited time span. Animations of this kind are usually used to animate the skeleton of a skinned mesh, but there are other uses as well.</p>
<p>An <a class="el" href="structai_animation.html" title="An animation consists of keyframe data for a number of nodes.">aiAnimation</a> has a duration. The duration as well as all time stamps are given in ticks. To get the correct timing, all time stamp thus have to be divided by <a class="el" href="structai_animation.html#afd26a40c3f16b6aa6e150effa3eaeab1" title="Ticks per second.">aiAnimation::mTicksPerSecond</a>. Beware, though, that certain combinations of file format and exporter don't always store this information in the exported file. In this case, mTicksPerSecond is set to 0 to indicate the lack of knowledge.</p>
<p>The <a class="el" href="structai_animation.html" title="An animation consists of keyframe data for a number of nodes.">aiAnimation</a> consists of a series of <a class="el" href="structai_node_anim.html" title="Describes the animation of a single node.">aiNodeAnim</a>'s. Each bone animation affects a single node in the node hierarchy only, the name specifying which node is affected. For this node the structure stores three separate key sequences: a vector key sequence for the position, a quaternion key sequence for the rotation and another vector key sequence for the scaling. All 3d data is local to the coordinate space of the node's parent, that means in the same space as the node's transformation matrix. There might be cases where animation tracks refer to a non-existent node by their name, but this should not be the case in your every-day data.</p>
<p>To apply such an animation you need to identify the animation tracks that refer to actual bones in your mesh. Then for every track: <br/>
 a) Find the keys that lay right before the current anim time. <br/>
 b) Optional: interpolate between these and the following keys. <br/>
 c) Combine the calculated position, rotation and scaling to a tranformation matrix <br/>
 d) Set the affected node's transformation to the calculated matrix. <br/>
</p>
<p>If you need hints on how to convert to or from quaternions, have a look at the <a href="http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix&amp;Quaternion FAQ</a>. I suggest using logarithmic interpolation for the scaling keys if you happen to need them - usually you don't need them at all.</p>
<h1><a class="anchor" id="textures"></a>
Textures</h1>
<p>Normally textures used by assets are stored in separate files, however, there are file formats embedding their textures directly into the model file. Such textures are loaded into an <a class="el" href="structai_texture.html" title="Helper structure to describe an embedded texture.">aiTexture</a> structure. <br/>
 There are two cases: <br/>
 <b>1)</b> The texture is NOT compressed. Its color data is directly stored in the <a class="el" href="structai_texture.html" title="Helper structure to describe an embedded texture.">aiTexture</a> structure as an array of <a class="el" href="structai_texture.html#aaa3ad8cfe44fdc4dea2db91977d92234" title="Width of the texture, in pixels.">aiTexture::mWidth</a> * <a class="el" href="structai_texture.html#ac1e2fa6f1f646e9c55e3985d4418a752" title="Height of the texture, in pixels.">aiTexture::mHeight</a> <a class="el" href="structai_texel.html" title="Helper structure to represent a texel in a ARGB8888 format.">aiTexel</a> structures. Each <a class="el" href="structai_texel.html" title="Helper structure to represent a texel in a ARGB8888 format.">aiTexel</a> represents a pixel (or "texel") of the texture image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for both Direct3D and OpenGL (swizzling the order of the color components might be necessary). RGBA8888 has been chosen because it is well-known, easy to use and natively supported by nearly all graphics APIs. <br/>
 <b>2)</b> This applies if <a class="el" href="structai_texture.html#ac1e2fa6f1f646e9c55e3985d4418a752" title="Height of the texture, in pixels.">aiTexture::mHeight</a> == 0 is fullfilled. Then, texture is stored in a "compressed" format such as DDS or PNG. The term "compressed" does not mean that the texture data must actually be compressed, however the texture was found in the model file as if it was stored in a separate file on the harddisk. Appropriate decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. <a class="el" href="structai_texture.html#aaa3ad8cfe44fdc4dea2db91977d92234" title="Width of the texture, in pixels.">aiTexture::mWidth</a> specifies the size of the texture data in bytes, <a class="el" href="structai_texture.html#a97dcffdd5651f20605750820dab897a7" title="Data of the texture.">aiTexture::pcData</a> is a pointer to the raw image data and <a class="el" href="structai_texture.html#aa9f44996acf3b301bfeb4e5348311540" title="A hint from the loader to make it easier for applications to determine the type of embedded compresse...">aiTexture::achFormatHint</a> is either zeroed or contains the most common file extension of the embedded texture's format. This value is only set if assimp is able to determine the file format. </p>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Tue Jul 10 2012 17:55:53 for Assimp by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.1.1
</small></address>
</body>
</html>
